using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Duckov.Utilities;
using ItemStatsSystem;
using ItemStatsSystem.Items;
using UnityEngine;

namespace IncreaseWeaponSlots
{
    public static class IncreaseWeaponSlotsUtils
    {
        // 分离tag名称和slot键名的映射
        private static readonly Dictionary<string, string> TagToSlotKeyMap = new Dictionary<string, string>
        {
            { "Scope", "Scope" }, // 瞄具
            { "Muzzle", "Muzzle" }, // 枪口
            { "Grip", "Grip" }, // 握把
            { "Stock", "Stock" }, // 枪托
            { "TecEquip", "Tec" }, // 战术
            { "Magazine", "Mag" } // 弹匣
        };

        private static readonly string[] KeysList =
        {
            "Scope", "Muzzle", "Grip", "Stock", "Tec", "Mag"
        };

        // 所有可应用于枪口/弹匣的约束标签
        private static readonly string[] GunTypeTagNames =
        {
            "GunType_AR", // 步枪
            "GunType_BR", // 战斗步枪
            "GunType_PST", // 手枪
            "GunType_SMG", // 冲锋枪
            "GunType_SNP", // 狙击枪
            "GunType_SHT", // 霰弹枪 - 只应用于枪口
        };

        // 缓存反射字段
        private static readonly FieldInfo? SlotKeyField;

        static IncreaseWeaponSlotsUtils()
        {
            // 初始化时缓存反射字段
            SlotKeyField = typeof(Slot).GetField("key",
                BindingFlags.NonPublic | BindingFlags.Instance);

            if (SlotKeyField == null)
            {
                ModLog.Error("无法找到Slot.key字段");
            }
        }

        public static Tag? GetTypeTag(Item item)
        {
            return item.Tags.FirstOrDefault(tag => Array.Exists(GunTypeTagNames, n => Tag.Match(tag, n)));
        }

        public static void LogItemInfo(Item item)
        {
            if (!item)
            {
                ModLog.Warning("尝试记录空物品的信息");
                return;
            }

            try
            {
                // 获取DisplayName
                var displayName = item.DisplayName;

                // 获取Item组件的实例ID
                var itemInstanceID = item.GetInstanceID();

                // 获取GameObject的实例ID
                var gameObjectInstanceID = item.gameObject.GetInstanceID();

                // 打印所有信息
                ModLog.Info($"物品信息 - " +
                            $"名称: {displayName}, " +
                            $"Item实例ID: {itemInstanceID}, " +
                            $"GameObject实例ID: {gameObjectInstanceID}"
                );

                DisplayTags(item.Tags);
            }
            catch (Exception ex)
            {
                ModLog.Error($"记录物品信息时出错: {ex.Message}");
            }
        }

        private static void DisplayTags(TagCollection tags)
        {
            var text = tags.Aggregate("[", (current, tag) => $"{current}|{tag}");

            ModLog.Info($"所有标签：{text}|]");
        }

        public static void SetAllSlot(SlotCollection sc)
        {
            if (!sc || sc.list == null || sc.Count < 6)
                return;

            foreach (var slot in sc.list)
            {
                slot.excludeTags.Clear();
                foreach (var tag in slot.requireTags.Where(tag => TagToSlotKeyMap.ContainsKey(tag.name)))
                {
                    slot.requireTags.Clear();
                    slot.requireTags.Add(tag);
                    break;
                }
            }
        }

        public static void AddSlotList(SlotCollection sc, Tag? typeTag)
        {
            if (!sc) return;

            sc.list ??= new List<Slot>();

            foreach (var (index, key) in MissingSlotTagKeys(sc.list))
            {
                // 通过slot key反向查找对应的tag名称
                var tagName = TagToSlotKeyMap.FirstOrDefault(x => x.Value == key).Key;
                if (string.IsNullOrEmpty(tagName))
                {
                    ModLog.Warning($"无法找到slot key '{key}'对应的tag名称");
                    continue;
                }

                var newSlot = CreateSlotByTagName(tagName, typeTag);

                // 如果索引有效，在指定位置插入，否则添加到末尾
                if (index >= 0 && index <= sc.list.Count)
                {
                    sc.list.Insert(index, newSlot);
                    ModLog.Info($"在位置 {index} 插入插槽: {key}");
                }
                else
                {
                    sc.list.Add(newSlot);
                    ModLog.Info($"添加插槽: {key}");
                }
            }

            ModLog.Info($"添加插槽完成，当前插槽数：{sc.list.Count}");
        }

        private static IEnumerable<(int, string)> MissingSlotTagKeys(List<Slot> list)
        {
            return TagToSlotKeyMap
                .Values
                .Except(list.Select(slot => slot.Key))
                .Select(key => (Array.IndexOf(KeysList, key), key));
        }

        public static void SetSlotList(SlotCollection sc, Tag? typeTag)
        {
            if (sc == null) return;

            // 如果sc.list为null，需要初始化
            if (sc.list == null)
            {
                sc.list = new List<Slot>();
            }
            else
            {
                // 清空现有的slot列表
                sc.list.Clear();
            }

            // 为每个标签名称创建并添加新的Slot
            foreach (var tagName in TagToSlotKeyMap.Keys)
            {
                var newSlot = CreateSlotByTagName(tagName, typeTag);
                if (newSlot != null)
                {
                    sc.list.Add(newSlot);
                }
            }

            ModLog.Info($"设置插槽完毕，当前插槽数：{sc.Count}");
        }

        private static Slot? CreateSlotByTagName(string tagName, Tag? typeTag)
        {
            var slot = new Slot();
            var tag = FindTagByName(tagName);
            if (tag)
            {
                slot.requireTags.Add(tag);
            }
            else
            {
                ModLog.Warning($"插槽Tag创建失败： {tagName}");
                return null;
            }

            if (!SetSlotKey(slot, tagName))
            {
                ModLog.Warning($"插槽Key设置失败： {tagName}");
                return null;
            }

            if (!typeTag) return slot;
            
            switch (tagName)
            {
                case "Scope" when typeTag != FindTagByName("GunType_SNP"):
                    slot.excludeTags.Add(FindTagByName("GunType_SNP"));
                    break;
                
                case "Muzzle":
                case "Magazine" when typeTag != FindTagByName("GunType_SHT"):
                    slot.requireTags.Add(typeTag);
                    break;
            }

            return slot;
        }

        private static bool SetSlotKey(Slot? slot, string tagName)
        {
            if (slot == null || SlotKeyField == null)
            {
                return false;
            }

            // 从映射字典中获取对应的slot key
            if (!TagToSlotKeyMap.TryGetValue(tagName, out var slotKey)) return false;
            
            SlotKeyField.SetValue(slot, slotKey);
            return true;

        }

        // 缓存Tag查找结果以避免重复查找
        private static readonly Dictionary<string, Tag?> TagCache = new Dictionary<string, Tag?>();

        private static Tag? FindTagByName(string tagName)
        {
            // 首先检查缓存
            if (TagCache.TryGetValue(tagName, out var cachedTag))
            {
                return cachedTag;
            }

            try
            {
                var allTags = Resources.FindObjectsOfTypeAll<Tag>();
                foreach (var loadedTag in allTags)
                {
                    if (loadedTag.name != tagName) continue;
                    
                    // 添加到缓存
                    TagCache[tagName] = loadedTag;
                    return loadedTag;
                }

                ModLog.Warning($"无法找到Tag: {tagName}");
                // 缓存null值以避免重复查找不存在的tag
                TagCache[tagName] = null;
                return null;
            }
            catch (Exception ex)
            {
                ModLog.Error($"查找Tag {tagName} 时出错: {ex.Message}");
                TagCache[tagName] = null;
                return null;
            }
        }
    }
}